import threading
import time, os
import requests, json
import shutil
import logging
from datetime import datetime
from hedra import devel_hedra
from qiniud import qiMainThead
import string, random

if not os.path.exists("res"):
    os.makedirs("res")
if not os.path.exists("logs"):
    os.makedirs("logs")
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("logs/hedra.log", encoding="utf-8")
handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

# 禁用安全请求警告
requests.packages.urllib3.disable_warnings(
    requests.packages.urllib3.exceptions.InsecureRequestWarning
)


def has_hexcode(len=3):
    """返回16禁止随机数"""
    return "".join(random.choice(string.hexdigits) for _ in range(len * 2)).upper()


def has_chocode(len=3, level=0):
    """返回随机数"""
    chars = string.digits
    if level > 0:
        chars += string.ascii_letters
    if level > 1:
        chars += string.punctuation
    return "".join(random.choice(chars) for _ in range(len)).upper()


def hasConf():
    """获取用户配置"""
    try:
        with open("conf.json", "r") as fs:
            return json.load(fs)
    except:
        return {}


CONF = hasConf()
if not CONF:
    logger.error("请先配置conf.json")
    raise Exception("请先配置conf.json")


class hasTasksRequest(requests.Session):
    # host = "http://lease.3vppt.com"
    # host = "http://192.168.31.211:8000"
    host = CONF.get("host", "http://192.168.31.211:8000")

    def do_get(self, url="", headers=None, params=None, data=None):
        url = self.host + url
        try:
            r = self.get(url, headers=headers, params=params, data=data, verify=False)
            return r.json() if r and r.status_code == 200 else {}
        except BaseException as err:
            logger.error(f"{err}")
            return {}

    def do_post(self, url="", headers=None, params=None, data=None, json=None):
        url = self.host + url
        try:
            r = self.post(
                url, headers=headers, params=params, data=data, json=json, verify=False
            )
            return r.json() if r and r.status_code == 200 else {}
        except BaseException as err:
            logger.error(f"{err}")
            return {}

    def has_tasksA(self):
        """获取音频合成任务"""
        url = "/rebot/postinfer/11/"
        headers = {"Content-Type": "application/json"}
        headers["NAME"] = "aniPortrait"
        headers["VERSION"] = "1.0.0"
        res = self.do_get(url, headers=headers)
        return res

    def has_tasksB(self):
        """获取视频合成任务"""
        url = "/rebot/postinfer/12/"
        headers = {"Content-Type": "application/json"}
        headers["NAME"] = "aniPortrait"
        headers["VERSION"] = "1.0.0"
        res = self.do_get(url, headers=headers)
        return res

    def has_attribute(self, uid):
        """查询AI属性"""
        url = f"/rebot/botList/{uid}/"
        headers = {"Content-Type": "application/json"}
        res = self.do_get(url, headers=headers)
        # print(res)
        return res

    def has_audio(self, uid):
        """查询音频属性"""
        url = f"/rebot/botConf/{uid}/"
        headers = {"Content-Type": "application/json"}
        res = self.do_get(url, headers=headers)
        return res

    def post_task_refer(self, guid, uid, code, data, types="Video"):
        """提交合成任务"""
        url = "/rebot/postinfer/"
        headers = {"Content-Type": "application/json"}
        headers["NAME"] = "aniPortrait"
        headers["VERSION"] = "1.0.0"
        data = {
            "guid": guid,
            "user": uid,
            "code": code,
            "data": data,
            "mode": types,
            "plan": "1/1",
        }
        res = self.do_post(url, headers=headers, data=json.dumps(data))
        print(f"任务完成:{res}")  # logger.info(f"任务完成:{types} {res}")
        return res


class myThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.shake = has_hexcode()
        self.is_Run = True
        self.web = hasTasksRequest()
        self.openEdge()

    def openEdge(self):
        """启动浏览器"""
        self.video = devel_hedra(CONF)
        self.video.open()
        self.video.do_main_console()
        self.air = datetime.now()

    def __del__(self):
        try:
            shutil.rmtree(f"res/{self.shake}/")
        except:
            pass
        self.video.close()
        logger.debug("myThread Thread is uniting...")

    def stop(self):
        self.video.close()
        self.is_Run = False

    def run(self):
        print("myThread Thread is running...")
        logger.debug("myThread Thread is running...")
        while self.is_Run:
            # 视频12
            task = self.web.has_tasksB().get("resmsg", None)
            if task:
                if not datetime.now().day == self.air.day:
                    self.video.close()
                    self.openEdge()
                print("新任务:", task)
                # 格式化数据
                box = self.formatMsgB(task)
                print(box)
                # 下载音频
                a = self.downloadAudio(self.shake, box.get("audio"))
                if not a:
                    logger.warning("音频下载失败")
                    self.web.post_task_refer(
                        box.get("guid"),
                        box.get("user"),
                        404,
                        "音频下载失败",
                        box.get("mode", "Video"),
                    )
                    continue
                # 下载图片
                p = self.downloadImage(self.shake, box.get("image"))
                if not p:
                    logger.warning("图片下载失败")
                    self.web.post_task_refer(
                        box.get("guid"),
                        box.get("user"),
                        404,
                        "图片下载失败",
                        box.get("mode", "Video"),
                    )
                    continue
                # 推理
                from hedra import devel_hedra

                # video = devel_hedra(CONF)
                # video.open()
                # video.do_main_console()
                mp4 = self.video.uploadRes(
                    [f"res/{self.shake}/image.png", f"res/{self.shake}/audio.wav"]
                )
                # video.close()
                if not mp4:
                    logger.warning("视频推理失败")
                    self.web.post_task_refer(
                        box.get("guid"),
                        box.get("user"),
                        404,
                        "视频推理失败",
                        box.get("mode", "Video"),
                    )
                    continue

                # 下载视频
                v = self.downloadVideo(self.shake, mp4)
                if not v:
                    logger.warning("视频下载失败")
                    self.web.post_task_refer(
                        box.get("guid"),
                        box.get("user"),
                        404,
                        "图片视频失败",
                        box.get("mode", "Video"),
                    )
                    continue

                # 上传文件
                r = qiMainThead().doUpload(v)
                if not r:
                    logger.warning("上传七牛云失败")
                    self.web.post_task_refer(
                        box.get("guid"),
                        box.get("user"),
                        404,
                        "上传七牛云失败",
                        box.get("mode", "Video"),
                    )
                    continue

                # print(
                #     f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 上传七牛云完成 https://oss.3vppt.com/{r.get("key")}'
                # )

                # 上传结果地址
                res = self.web.post_task_refer(
                    box.get("guid"),
                    box.get("user"),
                    200,
                    f'https://oss.3vppt.com/{r.get("key")}',
                    box.get("mode", "Video"),
                )

            time.sleep(3)

    def formatMsgB(self, msg):
        """返回: {'pswd': '123456', 'audio': url, 'image': url, 'guid': guid, 'mode': 'Video', 'answer': 1, 'user': 1}"""
        return eval(msg)

    def formatMsgA(self, msg):
        """返回: 类型, guid, 用户id, 内容"""
        r = eval(msg)
        return "Audio", r.get("guid"), r.get("user"), r.get("chat")

    @staticmethod
    def downloadAudio(path, url):
        try:
            res = f"res/{path}"
            if not os.path.exists(res):
                os.makedirs(res)
            r = requests.get(url, stream=True, timeout=5)
            if not r.status_code == 200:
                raise Exception("音频下载失败")
            with open(f"{res}/audio.wav", "wb") as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
        except BaseException as err:
            print(err)
            return None
        return f"{res}/audio.wav"

    @staticmethod
    def downloadImage(path, url):
        try:
            res = f"res/{path}"
            if not os.path.exists(res):
                os.makedirs(res)
            r = requests.get(url, stream=True, timeout=5)
            if not r.status_code == 200:
                raise Exception("音频下载失败")
            with open(f"{res}/image.png", "wb") as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
        except BaseException as err:
            print(err)
            return None
        return f"{res}/image.png"

    @staticmethod
    def downloadVideo(path, url):
        try:
            res = f"res/{path}"
            if not os.path.exists(res):
                os.makedirs(res)
            r = requests.get(url, stream=True, timeout=5)
            if not r.status_code == 200:
                raise Exception("音频下载失败")
            with open(f"{res}/video.mp4", "wb") as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
        except BaseException as err:
            print(err)
            return None
        return f"{res}/video.mp4"


if __name__ == "__main__":
    print(
        """
        视频生成  ver:1.2
        
    查看浏览器版本: edge://version/
    下载驱动: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/?form=MA13LH          
          """
    )
    logger.info("main start")
    print("...")
    [print(k, ": ", v) for k, v in CONF.items()]
    print("...\n")

    main = myThread()
    main.start()
    while True:
        x = input("请输入：[stop]")
        if x == "stop":
            main.stop()
            break
        if x == "start":
            main.start()
    main.join()
    logger.info("main stop")
    print("Bye")
